import javassist.util.proxy.MethodHandler;
import javassist.util.proxy.ProxyFactory;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

/**
 * Desc：代理模式(Proxy),为其他对象提供一种代理以控制对这个对象的访问.
 * Created by VincentZee on 2019/2/20
 */
public class ProxyPatternDemo{
    public static void main(String[] args) throws IllegalAccessException, InstantiationException {
        // 静态代理
        /*House houseProxy = new StaticProxy(new VincentZee());
        houseProxy.byHouse();*/

        VincentZee vincentZee = new VincentZee();
        // JDK动态代理
        /*JDKProxy jdkProxy = new JDKProxy(vincentZee);
        House house = (House) java.lang.reflect.Proxy.newProxyInstance(vincentZee.getClass().getClassLoader(),
                                                                        vincentZee.getClass().getInterfaces(), jdkProxy);
        house.byHouse();*/

        // CGLIB动态代理
        /*CGLibProxy cgLibProxy = new CGLibProxy();
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(VincentZee.class);
        enhancer.setCallback(cgLibProxy);
        House house = (House) enhancer.create();
        house.byHouse();*/

        // javaassist动态代理
        ProxyFactory proxyFactory = new ProxyFactory();
        proxyFactory.setSuperclass(VincentZee.class);
        proxyFactory.setHandler(new JavaassistProxy(vincentZee));
        House house = (House) proxyFactory.createClass().newInstance();
        house.byHouse();
    }
}

interface House{
    void byHouse();
}

class VincentZee implements House{

    @Override
    public void byHouse() {
        System.out.println("I'm VincentZee,finally i bought a house!");
    }
}

// 静态代理
class StaticProxy implements House{

    // 代理对象
    private VincentZee vincentZee;

    public StaticProxy(VincentZee vincentZee){
        this.vincentZee = vincentZee;
    }

    @Override
    public void byHouse() {
        System.out.println("Static Intermediary：start buy house!");
        vincentZee.byHouse();
        System.out.println("Static Intermediary：end buy house!");
    }
}


// JDK动态代理(反射原理)
class JDKProxy implements InvocationHandler{

    private Object target;

    JDKProxy(Object target){
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("JDK Intermediary：start buy house!");
        Object invoke = method.invoke(target, args);
        System.out.println("JDK Intermediary：end buy house!");
        return invoke;
    }
}

// CGLIB动态代理(字节码操作库)
class CGLibProxy implements MethodInterceptor {

    @Override
    public Object intercept(Object obj, Method method, Object[] arrays, MethodProxy methodProxy) throws Throwable {
        System.out.println("CGLib Intermediary：start buy house!");
        Object invokeSuper = methodProxy.invokeSuper(obj, arrays);
        System.out.println("CGLib Intermediary：end buy house!");
        return invokeSuper;
    }
}

// javaassist动态代理(字节码操作库)
class JavaassistProxy implements MethodHandler{
    private Object target;

    JavaassistProxy(Object target){
        this.target = target;
    }

    @Override
    public Object invoke(Object self, Method thisMethod, Method proceed, Object[] args) throws Throwable {
        System.out.println("Javaassist Intermediary：start buy house!");
        thisMethod.invoke(target, args);
        System.out.println("Javaassist Intermediary：end buy house!");
        return self;
    }
}
